<?php
require_once __DIR__ . "/Loadfile.php";
require_once __DIR__ . "/Database.php";
require_once __DIR__ . "/Router.php";

class AppContainer
{
        public $db;
        public $userDao;
        public $userController;
        public $router;

        public function __construct()
        {
                $this->db = new Database();
                $this->router = new Router();
                $this->init();
                // $this->userDao = new UserDao();
                // $this->userDao->setDb($this->db);
                // $this->userController = new UserController($this->userDao);
        }
        /*
         加载config/api/**Controller.php文件, dao/**Dao.php文件，并根据这些文件创建对象，创建**Controller对象的时候，注入**Dao对象， 
         将**Controller对象注入到容器中
          */
        public function init()
        {
                $this->loadDb();
                $this->loadDao();
                $this->loadController();
                // $this->initRouter();
        }
        public function loadDb()
        {
                $this->set("db", new Database());
        }
        public function loadController()
        {
                $files = glob(__DIR__ . "/../controller/api/*.php");
                foreach ($files as $file) {
                        $className = pathinfo($file, PATHINFO_FILENAME);
                        $class = new ReflectionClass($className);
                        $constructor = $class->getConstructor();
                        if (!isset($constructor)) {
                                continue;
                        }
                        $params = $constructor->getParameters();
                        $dependencies = [];
                        foreach ($params as $param) {
                                $paramType = $param->getType();
                                if ($paramType) {
                                        $dependencies[] = $this->get(lcfirst($paramType->getName()));
                                }
                        }
                        $controller = $class->newInstanceArgs($dependencies);
                        $this->set(lcfirst($className), $controller);
                }
        }
        public function loadDao()
        {
                $files = glob(__DIR__ . "/../dao/*.php");
                foreach ($files as $file) {
                        $className = pathinfo($file, PATHINFO_FILENAME);
                        // 
                        $class = new ReflectionClass($className);
                        $constructor = $class->getConstructor();
                        if ($constructor) {
                                $params = $constructor->getParameters();
                                $dependencies = [];
                                foreach ($params as $param) {
                                        $dependency = $param->getType();
                                        if ($dependency->getName() === 'Database') {
                                                $dependencies[] = $this->get("db");
                                        } elseif ($dependency) {
                                                $dependencies[] = $this->get(lcfirst($dependency->getName()));
                                        }
                                }
                                $dao = $class->newInstanceArgs($dependencies);
                        } else {
                                $dao = $class->newInstance();
                                $dbProperty = $class->getProperty("db");
                                $dbProperty->setAccessible(true);
                                $dbProperty->setValue($dao, $this->db);
                        }
                        $this->set(lcfirst($className), $dao);
                }
                // 数组转换成字符串
                // error_log(implode(",", $files));
        }
        public function set($key, $value)
        {
                $this->$key = $value;
        }
        public function get($key)
        {
                return $this->$key;
        }





        // 设置映射关系， 存储url和控制器的映射关系
// 编写这样的路由Router类，
// 提供addRoute方法，可以添加路由规则
// 提供match方法，可以匹配请求的url和控制器的映射关系

        // 注册路由
        public function initRoute()
        {
                $this->addRoute("GET", "/", "IndexControlle#index");
                $this->addRoute("GET", "/api/users", "userController#users");
                $this->addRoute("GET", "regex:/^\/api\/user\/(\d+)$/", "userController#getUserById");
                $this->addRoute("POST", "/api/user", "userController#addUser");
                $this->addRoute("PUT", "regex:/^\/api\/user\/(\d+)$/", "userController#editUser");
                $this->addRoute("DELETE", "regex:/^\/api\/user\/(\d+)$/", "userController#deleteUser");
        }
        public function addRoute($method, $url, $handlerAction)
        {
                // $handlerAction 格式是userController#users
                $controllerClass = explode("#", $handlerAction)[0];
                $action = explode("#", $handlerAction)[1];
                if (!class_exists($controllerClass) || !$this->get($controllerClass)) {
                        error_log("controller class " . $controllerClass . " not exists or not set in container");
                        return;
                }
                $this->router->addRoute($method, $url, $this->get($controllerClass), $action);
        }
}